package com.microblogforsim.ui;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ImageView;

import androidx.annotation.RequiresApi;

import static android.content.ContentValues.TAG;
import static android.net.wifi.WifiConfiguration.Status.ENABLED;

public class TouchImageView extends androidx.appcompat.widget.AppCompatImageView {
    //是否释放了
    private boolean isReleased;
    //计数器，防止多次点击导致最后一次形成longpress的时间变短
    private int mCounter;
    //长按的runnable
    private Runnable mLongPressRunnable;
    //定义相应时间 以此为依据判断是长按还是短按 默认为300毫秒
    private int minTime = 300;

    private float mOldX;
    private float mOldY;
    private float mCurrentX;
    private float mCurrentY;
    private int state = -1;
    public static final int left = 1;
    public static final int right = 2;
    public static final int normal = 3;

    public int getMinTime() {
        return minTime;
    }

    public void setMinTime(int minTime) {
        this.minTime = minTime;
    }

    private PointF down = new PointF();
    private PointF mid = new PointF();
    private float oldDist = 1f;
    private Matrix matrix = new Matrix();
    private Matrix preMatrix = new Matrix();
    private Matrix savedMatrix = new Matrix();

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;

    private boolean isBig = false;

    private int widthScreen;
    private int heightScreen;

    private int touchImgWidth;
    private int touchImgHeight;

    private float defaultScale;

    private long lastClickTime = 0;

    private Bitmap touchImg = null;

    private static final int DOUBLE_CLICK_TIME_SPACE = 300;
    private static final int DOUBLE_POINT_DISTANCE = 10;
    private static float MAX_SCALE = 10.0f;

    public TouchImageView(Context context) {
        super(context);
    }

    public TouchImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


    }
    public TouchImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        this(context, attrs, defStyleAttr);
    }

    public void initImageView(int screenWidth, int screenHeight) {
        widthScreen = screenWidth;
        heightScreen = screenHeight;

        touchImg = ((BitmapDrawable) getDrawable()).getBitmap();
        touchImgWidth = touchImg.getWidth();
        touchImgHeight = touchImg.getHeight();
        float scaleX = (float) widthScreen / touchImgWidth;
        float scaleY = (float) heightScreen / touchImgHeight;
        defaultScale = scaleX < scaleY ? scaleX : scaleY;

        float subX = (widthScreen - touchImgWidth * defaultScale) / 2;
        float subY = (heightScreen - touchImgHeight * defaultScale) / 2;
        setScaleType(ScaleType.MATRIX);
        preMatrix.reset();
        preMatrix.postScale(defaultScale, defaultScale);
        preMatrix.postTranslate(subX, subY);
        matrix.set(preMatrix);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (null != touchImg) {
            canvas.save();
            canvas.drawBitmap(touchImg, matrix, null);
            canvas.restore();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {

            case MotionEvent.ACTION_DOWN:
                mOldX = event.getX();
                mOldY = event.getY();
                state = normal;

                mode = DRAG;
                down.x = event.getX();
                down.y = event.getY();
                savedMatrix.set(matrix);

                if (event.getEventTime() - lastClickTime < DOUBLE_CLICK_TIME_SPACE) {
                    changeSize(event.getX(), event.getY());
                }
                lastClickTime = event.getEventTime();
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > DOUBLE_POINT_DISTANCE) {
                    mode = ZOOM;
                    // oldRotation = rotation(event);
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == ZOOM) {
                    float newDist = spacing(event);
                    float scale = newDist / oldDist;
                    if (scale > 1.01 || scale < 0.99) {
                        preMatrix.set(savedMatrix);
                        preMatrix.postScale(scale, scale, mid.x, mid.y);// 缩放
                        if (canZoom()) {
                            matrix.set(preMatrix);
                            invalidate();
                        }
                    }
                } else if (mode == DRAG) {
                    if (1.0f < distance(event, down)) {
                        preMatrix.set(savedMatrix);

                        preMatrix.postTranslate(event.getX() - down.x, 0);
                        if (event.getX() > down.x) {
                            if (canDrag(DRAG_RIGHT)) {
                                savedMatrix.set(preMatrix);
                            } else {
                                preMatrix.set(savedMatrix);
                            }
                        } else {
                            if (canDrag(DRAG_LEFT)) {
                                savedMatrix.set(preMatrix);
                            } else {
                                preMatrix.set(savedMatrix);
                            }
                        }
                        preMatrix.postTranslate(0, event.getY() - down.y);
                        if (event.getY() > down.y) {
                            if (canDrag(DRAG_DOWN)) {
                                savedMatrix.set(preMatrix);
                            } else {
                                preMatrix.set(savedMatrix);
                            }
                        } else {
                            if (canDrag(DRAG_TOP)) {
                                savedMatrix.set(preMatrix);
                            } else {
                                preMatrix.set(savedMatrix);
                            }
                        }

                        matrix.set(preMatrix);
                        invalidate();
                        down.x = event.getX();
                        down.y = event.getY();
                        savedMatrix.set(matrix);
                    }
                }

                mCurrentX = event.getX();
                mCurrentY = event.getY();
                if (mCurrentX - mOldX > 0 && Math.abs(mCurrentY - mOldY) < 10) {
                    state = right;
                    Log.d(TAG, "向右>>>>");
                }
                else if (mCurrentX - mOldX < 0
                        && Math.abs(mCurrentY - mOldY) < 10) {
                    state = left;
                    Log.d(TAG, "向向左>>>>");


                }
                else if (mCurrentY - mOldY > 0
                        && Math.abs(mCurrentX - mOldX) < 10) {

                }
                else if (mCurrentY - mOldY < 0
                        && Math.abs(mCurrentX - mOldX) < 10) {
                }
                break;
            case MotionEvent.ACTION_UP:

                mode = NONE;
                springback();
                switch (state) {
                    case right:
                       onMoveImageView.last();
                        Log.d(TAG, "向right up  ");
                        break;
                    case left:
                        onMoveImageView.next();
                        Log.d(TAG, "向向左 up  ");
                        break;
                    case normal:
                        onMoveImageView.click();
                        break;
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }
        return true;
    }

    private void springback() {
        preMatrix.set(matrix);
        float[] x = new float[4];
        float[] y = new float[4];
        getFourPoint(x, y);
        if (x[1] - x[0] > widthScreen) {
            if (x[0] > 0) {
                preMatrix.postTranslate(-x[0], 0);
                matrix.set(preMatrix);
                invalidate();
            } else if (x[1] < widthScreen) {
                preMatrix.postTranslate(widthScreen - x[1], 0);
                matrix.set(preMatrix);
                invalidate();
            }
        } else if (x[1] - x[0] < widthScreen - 1f) {
            preMatrix.postTranslate((widthScreen - (x[1] - x[0])) / 2 - x[0], 0);
            matrix.set(preMatrix);
            invalidate();
        }

        if (y[2] - y[0] > heightScreen) {
            if (y[0] > 0) {
                preMatrix.postTranslate(0, -y[0]);
                matrix.set(preMatrix);
                invalidate();
            } else if (y[2] < heightScreen) {
                preMatrix.postTranslate(0, heightScreen - y[2]);
                matrix.set(preMatrix);
                invalidate();
            }
        } else if (y[2] - y[0] < heightScreen - 1f) {
            preMatrix.postTranslate(0, (heightScreen - (y[2] - y[0])) / 2
                    - y[0]);
            matrix.set(preMatrix);
            invalidate();
        }
    }

    private void getFourPoint(float[] x, float[] y) {
        float[] f = new float[9];
        preMatrix.getValues(f);
        // 图片4个顶点的坐标
        x[0] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X] * 0
                + f[Matrix.MTRANS_X];
        y[0] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y] * 0
                + f[Matrix.MTRANS_Y];
        x[1] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X] * 0
                + f[Matrix.MTRANS_X];
        y[1] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y] * 0
                + f[Matrix.MTRANS_Y];
        x[2] = f[Matrix.MSCALE_X] * 0 + f[Matrix.MSKEW_X]
                * touchImg.getHeight() + f[Matrix.MTRANS_X];
        y[2] = f[Matrix.MSKEW_Y] * 0 + f[Matrix.MSCALE_Y]
                * touchImg.getHeight() + f[Matrix.MTRANS_Y];
        x[3] = f[Matrix.MSCALE_X] * touchImg.getWidth() + f[Matrix.MSKEW_X]
                * touchImg.getHeight() + f[Matrix.MTRANS_X];
        y[3] = f[Matrix.MSKEW_Y] * touchImg.getWidth() + f[Matrix.MSCALE_Y]
                * touchImg.getHeight() + f[Matrix.MTRANS_Y];
    }

    private final static int DRAG_LEFT = 0;
    private final static int DRAG_RIGHT = 1;
    private final static int DRAG_TOP = 2;
    private final static int DRAG_DOWN = 3;

    private boolean canDrag(final int direction) {
        float[] x = new float[4];
        float[] y = new float[4];
        getFourPoint(x, y);

        // 出界判断
        if ((x[0] > 0 || x[2] > 0 || x[1] < widthScreen || x[3] < widthScreen)
                && (y[0] > 0 || y[1] > 0 || y[2] < heightScreen || y[3] < heightScreen)) {
            return false;
        }
        if (DRAG_LEFT == direction) {
            // 左移出界判断
            if (x[1] < widthScreen || x[3] < widthScreen) {
                return false;
            }
        } else if (DRAG_RIGHT == direction) {
            // 右移出界判断
            if (x[0] > 0 || x[2] > 0) {
                return false;
            }
        } else if (DRAG_TOP == direction) {
            // 上移出界判断
            if (y[2] < heightScreen || y[3] < heightScreen) {
                return false;
            }
        } else if (DRAG_DOWN == direction) {
            // 下移出界判断
            if (y[0] > 0 || y[1] > 0) {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }

    private boolean canZoom() {
        float[] x = new float[4];
        float[] y = new float[4];
        getFourPoint(x, y);
        // 图片现宽度
        double width = Math.sqrt((x[0] - x[1]) * (x[0] - x[1]) + (y[0] - y[1])
                * (y[0] - y[1]));
        double height = Math.sqrt((x[0] - x[2]) * (x[0] - x[2]) + (y[0] - y[2])
                * (y[0] - y[2]));
        // 缩放比率判断
        if (width < touchImgWidth * defaultScale - 1
                || width > touchImgWidth * MAX_SCALE + 1) {
            return false;
        }

        // 出界判断
        if (width < widthScreen && height < heightScreen) {
            return false;
        }
        return true;
    }

    // 触碰两点间距离
    private static float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        if (x < 0) {
            x = -x;
        }
        float y = event.getY(0) - event.getY(1);
        if (y < 0) {
            y = -y;
        }
        return (float) Math.sqrt(x * x + y * y);
    }

    // 取手势中心点
    private static void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    // 取两点之间的距离
    private static float distance(MotionEvent point2, PointF point1) {
        float x = point1.x - point2.getX();
        if (x < 0) {
            x = -x;
        }
        float y = point1.y - point2.getY();
        if (y < 0) {
            y = -y;
        }
        return  (float)Math.sqrt(x * x + y * y);
    }

    private void changeSize(float x, float y) {
        if (isBig) {
            float subX = (widthScreen - touchImgWidth * defaultScale) / 2;
            float subY = (heightScreen - touchImgHeight * defaultScale) / 2;
            preMatrix.reset();
            preMatrix.postScale(defaultScale, defaultScale);
            preMatrix.postTranslate(subX, subY);
            matrix.set(preMatrix);
            invalidate();

            isBig = false;
        } else {
            float transX = (widthScreen - touchImgWidth * MAX_SCALE) / 2;
            float transY = (heightScreen - touchImgHeight * MAX_SCALE) / 2;
            preMatrix.reset();
            preMatrix.postScale(MAX_SCALE, MAX_SCALE);
            preMatrix.postTranslate(transX, transY);
            matrix.set(preMatrix);
            invalidate();

            isBig = true;
        }
    }


//    public boolean dispatchTouchEvent(MotionEvent event) {
//        switch(event.getAction()) {
//            case MotionEvent.ACTION_DOWN:
//                mCounter++;
//                isReleased = false;
//                postDelayed(mLongPressRunnable, minTime);
//                break;
//
//            case MotionEvent.ACTION_UP:
//                //释放了
//                isReleased = true;
//                break;
//        }
//        return true;
//    }



    private OnMoveImageView onMoveImageView;

    public OnMoveImageView getOnMoveImageView() {
        return onMoveImageView;
    }

    public void setOnMoveImageView(OnMoveImageView onMoveImageView) {
        this.onMoveImageView = onMoveImageView;
    }

    /*
     *左右滑动点击的回调接口
     */
    public  interface OnMoveImageView{
         void next();
         void last();
         void click();
    }



}

